home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / video / fly8111-.000 / fly8111- / fly8 / max.c < prev    next >
C/C++ Source or Header  |  1979-12-31  |  7KB  |  411 lines

  1. /* --------------------------------- max.c ---------------------------------- */
  2.  
  3. /* This is part of the flight simulator 'fly8'.
  4.  * Author: Eyal Lebedinsky (eyal@ise.canberra.edu.au).
  5. */
  6.  
  7. /* Read a text macro definition. Directly replaces mac_read() of macros.c.
  8. */
  9.  
  10. #include "fly.h"
  11. #include "keyname.h"
  12.  
  13.  
  14. static Ulong lineno = 1L, column = 0L, errs = 0L;
  15. static int    eof = 1, pushback = 0;
  16. static int    pushbuff[10] = {0};
  17. static char tabCTRL[] = "@abcdefghijklmnopqrstuvwxyz[\\]^_";
  18. static Ushort buf_str[1024] = {0};
  19.  
  20.  
  21. LOCAL_FUNC int NEAR
  22. keyval (int c)
  23. {
  24.     if (c >= 0 && c < 32)
  25.         c = tabCTRL[c] | K_CTRL;
  26.     return (c);
  27. }
  28.  
  29. LOCAL_FUNC int NEAR
  30. nlfgetc (FILE *f)
  31. {
  32.     int    c;
  33.  
  34.     if (pushback) {
  35.         c = pushbuff[--pushback];
  36.         return (c);
  37.     }
  38.  
  39.     if (eof)
  40.         return (EOF);
  41.  
  42.     c = fgetc (f);
  43.     ++column;
  44.     if ('\n' == c) {
  45.         ++lineno;
  46.         column = 0;
  47.     } else if (EOF == c)
  48.         eof = 1;
  49.  
  50.     return (c);
  51. }
  52.  
  53. LOCAL_FUNC Ulong NEAR
  54. eatline (FILE *f)
  55. {
  56.     int    c;
  57.  
  58.     do {
  59.         c = nlfgetc (f);
  60.     } while (EOF != c && '\n' != c);
  61.     return (EOF == c ? VK_EOF : (Ulong)c);
  62. }
  63.  
  64. LOCAL_FUNC int NEAR
  65. getbase (FILE *f, int base, int n, int c)
  66. {
  67.     int    i;
  68.  
  69.     for (i = 0;;) {
  70.         if (c >= '0' && c <= '9')
  71.             c -= '0';
  72.         else if (c >= 'a' && c <= 'f')
  73.             c -= 'a' - 10;
  74.         else if (c >= 'A' && c <= 'F')
  75.             c -= 'A' - 10;
  76.         else {
  77.             pushbuff[pushback++] = c;
  78.             break;
  79.         }
  80.         if (c >= base)
  81.             break;
  82.         i = i * base + c;
  83.         if (--n < 0)
  84.             break;
  85.         c = nlfgetc (f);
  86.     }
  87.  
  88.     if (i >= 256) {
  89.         ++errs;
  90.         MsgEPrintf (-50,
  91.             "max: escaped value too big at %ld:%ld",
  92.             lineno, column);
  93.         i &= 0x00ff;
  94.     }
  95.     return (i);
  96. }
  97.  
  98. LOCAL_FUNC int NEAR
  99. getescape (FILE *f)
  100. {
  101.     int    c;
  102.  
  103.     c = nlfgetc (f);
  104.  
  105.     switch (c) {
  106.     case 'a':
  107.         c = 'g';
  108.         break;
  109.     case 'b':
  110.         c = 'h';
  111.         break;
  112.     case 'e':
  113.         c = '[';
  114.         break;
  115.     case 'f':
  116.         c = 'l';
  117.         break;
  118.     case 'n':
  119.         c = 'm';
  120.         break;
  121.     case 'r':
  122.         c = 'j';
  123.         break;
  124.     case 't':
  125.         c = 'i';
  126.         break;
  127.     case 'v':
  128.         c = 'k';
  129.         break;
  130.     case '\n':
  131.         c = -1;        /* traditional line break */
  132.         goto raw;
  133.     case '0':
  134.         c = keyval (getbase (f, 8, 3, '0'));
  135.         goto raw;
  136.     case '1':
  137.     case '2':
  138.     case '3':
  139.     case '4':
  140.     case '5':
  141.     case '6':
  142.     case '7':
  143.     case '8':
  144.     case '9':
  145.         c = keyval (getbase (f, 10, 2, c));
  146.         goto raw;
  147.     case 'x':
  148.         c = keyval (getbase (f, 16, 2, '0'));
  149.         goto raw;
  150.     default:
  151.         goto raw;
  152.     }
  153.     c |= K_CTRL;
  154. raw:
  155.     return (c);
  156. }
  157.  
  158. LOCAL_FUNC int NEAR
  159. getstring (FILE *f)
  160. {
  161.     int    c, n;
  162.  
  163.     for (n = 0;;) {
  164.         c = nlfgetc (f);
  165.         if (EOF == c) {
  166.             ++errs;
  167.             MsgEPrintf (-50, "max: EOF inside string at %ld:%ld",
  168.                 lineno, column);
  169.             n = -1;
  170.             break;
  171.         }
  172.         if ('\\' == c) {
  173.             c = getescape (f);
  174.             if (-1 == c)
  175.                 continue;
  176.         } else if ('"' == c)
  177.             break;
  178.         else if ('\n' == c)        /* simplified line break */
  179.             continue;
  180.         else
  181.             c = keyval (c);
  182.         if (n >= rangeof (buf_str)) {
  183.             ++errs;
  184.             MsgEPrintf (-50, "max: string too long at %ld:%ld",
  185.                 lineno, column);
  186.             continue;
  187.         }
  188.         buf_str[n++] = (Ushort)c;
  189.     }
  190.     return (n);
  191. }
  192.  
  193. LOCAL_FUNC Ulong NEAR
  194. getterm (FILE *f)
  195. {
  196.     char    keyname[32+1];
  197.     int    n, i, c;
  198.  
  199. retry:
  200.     for (n = 0;;) {
  201.         c = nlfgetc (f);
  202.         if (EOF == c) {
  203.             if (n)
  204.                 break;
  205.             return (VK_EOF);
  206.         }
  207.         if (isspace (c)) {
  208.             if (n)
  209.                 break;
  210.             continue;
  211.         }
  212.         if ('\\' == c) {
  213.             if (n) {
  214.                 ++errs;
  215.                 MsgEPrintf (-50, "max: bad escape at %ld:%ld",
  216.                     lineno, column);
  217.                 continue;
  218.             }
  219.             c = getescape (f);
  220.             if (-1 == c)
  221.                 continue;
  222.             return (c);
  223.         }
  224.         if (n < sizeof (keyname) - 1) {
  225.             if (0 == n) {
  226.                 if ('"' == c)
  227.                     return (VK_STR);
  228.                 if ('#' == c)
  229.                     return (VK_COM);
  230.             }
  231.             keyname[n++] = (char)c;
  232.         } else
  233.             {/* truncate... */}
  234.     }
  235.     keyname[n] = '\0';
  236.  
  237. /* Look word up
  238. */
  239.     for (i = 0; k_name[i].name; ++i) {
  240.         if (!stricmp (k_name[i].name, keyname))
  241.             return (k_name[i].value);
  242.     }
  243.  
  244.     if (1 == n)
  245.         return (keyval(*(Uchar *)keyname));
  246.  
  247.     ++errs;
  248.     MsgEPrintf (-50, "max: bad token '%s' at %ld:%ld", keyname,
  249.         lineno, column);
  250.     if (EOF == c)
  251.         return (VK_EOF);
  252.  
  253.     goto retry;
  254. }
  255.  
  256. LOCAL_FUNC Ulong NEAR
  257. maxkey (FILE *f)
  258. {
  259.     Ulong    c, key;
  260.  
  261.     for (key = 0L;;) {
  262.         c = getterm (f);
  263.         if (VK_EOF == c) {
  264.             if (key) {
  265.                 ++errs;
  266.                 MsgEPrintf (-50,
  267. "max: unexpected end of file at %ld:%ld",
  268.                     lineno, column);
  269.             }
  270.             return (VK_EOF);
  271.         } else if (VK_DEF == c) {
  272.             if (key) {
  273.                 ++errs;
  274.                 MsgEPrintf (-50,
  275. "max: bad key preceding 'def' at %ld:%ld",
  276.                     lineno, column);
  277.             }
  278.             key = VK_DEF;
  279.         } else if (VK_COM == c) {
  280.             if (key) {
  281.                 ++errs;
  282.                 MsgEPrintf (-50,
  283. "max: bad key preceding comment at %ld:%ld",
  284.                     lineno, column);
  285.             }
  286.             key = 0L;
  287.             c = eatline (f);
  288.             if (VK_EOF == c)
  289.                 return (VK_EOF);
  290.         } else if (VK_STR == c) {
  291.             if (key) {
  292.                 ++errs;
  293.                 MsgEPrintf (-50,
  294. "max: bad key preceding string at %ld:%ld",
  295.                     lineno, column);
  296.             }
  297.             return (VK_STR);
  298.         } else {
  299.             key |= c;
  300.             if (c & K_RAW)
  301.                 return (key);
  302.         }
  303.     }
  304.     /* never reached */
  305. }
  306.  
  307. #define MAXMACLEN    1024
  308.  
  309. extern int FAR
  310. max_read (MACRO *Macros)
  311. {
  312.     FILE    *max = NULL;
  313.     int    i, n, nMacros;
  314.     Ulong    c;
  315.     MACRO    *m;
  316.     Ushort    *macbody;
  317.  
  318.     macbody = (Ushort *)memory_calloc (MAXMACLEN, sizeof (*macbody));
  319.  
  320.     Sys->BuildFileName (st.filename, st.fdir, st.mname, MAX_EXT);
  321.     max = fopen (st.filename, RTMODE);
  322.     if (!max) {
  323.         MsgEPrintf (-50, "max: open '%s' failed",
  324.             st.filename);
  325.         ++errs;
  326.         goto ret;
  327.     }
  328.     eof = 0;
  329.     pushback = 0;
  330.     LogPrintf ("Max      %s\n", st.filename);
  331.  
  332.     for (m = Macros, nMacros = 0;;) {
  333.         c = maxkey (max);
  334.         if (VK_EOF == c)
  335.             break;
  336.         if (!(VK_DEF & c)) {
  337.             ++errs;
  338.             MsgEPrintf (-50, "max: 'def' not found at %ld:%ld",
  339.                 lineno, column);
  340.             continue;
  341.         }
  342. def:
  343.         if (nMacros > st.nMacros) {
  344.             ++errs;
  345.             MsgEPrintf (-50, "max: too many macros at %ld:%ld",
  346.                 lineno, column);
  347.             break;
  348.         }
  349.         m->name = (Ushort)c;
  350.         for (n = 0;;) {
  351.             c = maxkey (max);
  352.             if (VK_EOF == c || (VK_DEF & c))
  353.                 break;
  354.             if (VK_STR == c) {
  355.                 i = getstring (max);
  356.                 if (i <= 0)
  357.                     continue;
  358.                 if (n+i > MAXMACLEN) {
  359.                     ++errs;
  360.                     MsgEPrintf (-50,
  361. "max: macro too long at %ld:%ld", lineno, column);
  362.                 } else {
  363.                     memcpy (macbody+n, buf_str,
  364.                         i * sizeof (Ushort));
  365.                     n += i;
  366.                 }
  367.                 continue;
  368.             }
  369.             if (n >= MAXMACLEN) {
  370.                 ++errs;
  371.                 MsgEPrintf (-50,
  372.                     "max: macro too long at %ld:%ld",
  373.                     lineno, column);
  374.                 continue;
  375.             }
  376.             macbody[n++] = (Ushort)c;
  377.         }
  378.         if (0 == n) {
  379.             ++errs;
  380.             MsgEPrintf (-50, "max: empty macro at %ld:%ld",
  381.                 lineno, column);
  382.         }
  383.         m->len = (Ushort)n;
  384.         m->def = (Ushort *)memory_calloc (m->len, sizeof (*m->def));
  385.         if (!m->def) {
  386.             ++errs;
  387.             MsgEPrintf (-50, "max: no mem");
  388.             m->name = KEYUNUSED;
  389.             goto ret;
  390.         }
  391.         memcpy (m->def, macbody, m->len * sizeof (*m->def));
  392.         ++m;
  393.         ++nMacros;
  394.         if (VK_DEF & c)
  395.             goto def;
  396.         if (VK_EOF == c)
  397.             break;
  398.     }
  399. ret:
  400.     if (max) {
  401.         fclose (max);
  402.         max = NULL;
  403.     }
  404.     eof = 1;
  405.     pushback = 0;
  406.     macbody = memory_cfree (macbody, MAXMACLEN, sizeof (*macbody));
  407.     return (0 != errs);
  408. }
  409.  
  410. #undef MAXMACLEN
  411.